package main

import (
	"database/sql"
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"
	_ "github.com/go-sql-driver/mysql"
)

// 限制goroutine数量
var limitChan = make(chan bool, 1000)
var cnt int64
var serverity =[...]string{"Emergency","Alert","Critical", "Error", "Warning", "Notice",  "Info","Debug"}
var facility  =[...]string{
	"0 kernel messages",
	"1 user-level messages",
	"2 mail system",
	"3 system daemons",
	"4 security/authorization messages",
	"5 messages generated internally by syslogd",
	"6 line printer subsystem",
	"7 network news subsystem",
	"8 UUCP subsystem",
	"9 clock daemon",
	"10 security/authorization messages",
	"11 FTP daemon",
	"12 NTP subsystem",
	"13 log audit",
	"14 log alert",
	"15 clock daemon",
	"16 local0",
	"17 local7",
	"18 local7",
	"19 local7",
	"20 local7",
	"21 local7",
	"22 local7",
	"23 local7"}


func checkErr(errMasg error) {
	if errMasg != nil {
		panic(errMasg)
	}
}

// UDP goroutine 实现并发读取UDP数据
func udpProcess(conn *net.UDPConn, db *sql.DB) {

	// 最大读取数据大小
	data := make([]byte, 1024)
	n, clientip, err := conn.ReadFromUDP(data)
	if err != nil {
		fmt.Println("failed read udp msg, error: " + err.Error())
	}
	str := string(data[:n])
	a := strings.Index(str, "<")+1
	b := strings.Index(str, ">")
	lev := str[a:b]
	pri , _ := strconv.Atoi(lev)

	 ilev := pri & 7

	cip := clientip.IP.String()
	sqlstr := "insert into log(clientip, pri, lev,levinfo, msg) values(?,?,?,?,?)"

	tx, _ := db.Begin()
	ors, err := db.Prepare(sqlstr)
	_, err = ors.Exec(cip, pri, ilev, serverity[ilev], str)
	//checkErr(err)
	tx.Commit()

	cnt += 1
	fmt.Println(strconv.FormatInt(cnt, 10) +">"+ clientip.IP.String() +"["+ strconv.Itoa(ilev) + serverity[ilev] + "]#" + str)
	<-limitChan
}

func udpServer(address string) {
	udpAddr, err := net.ResolveUDPAddr("udp", address)
	conn, err := net.ListenUDP("udp", udpAddr)

	const (
		db_driver_name = "mysql"
		db_name        = "root:delphi@tcp(127.0.0.1:3306)/wlsbzz?utf8mb4"
	)

	db, err := sql.Open(db_driver_name, db_name)
	checkErr(err)

	defer conn.Close()
	if err != nil {
		fmt.Println("read from connect failed, err:" + err.Error())
		os.Exit(1)
	}

	for {
		limitChan <- true
		go udpProcess(conn, db)
	}
}

func main() {
	address := "0.0.0.0:514"
	fmt.Println("start:>")
	udpServer(address)
}
